/* 功能名称：元素拖拽功能
 * 作者：Vee7
 * 日期：2024-04-28
 * 功能描述：实现只需专注于元素的样式即可实现拖拽任意元素的拖拽功能,并可设置是否允许超出页面范围,
 * 超出回弹方式,及是否影响页面布局等功能,详细功能见参数。
 * 使用方法：在需要拖拽的元素上添加v-mov指令，并传入对象参数{title,position、overflow}，若不传递则为默认选项。
 * 
 * 参数说明：
 * title（是否通过title元素进行拖拽）:
 *      true-通过class为title的元素进行拖拽
 *      false/默认-通过指令所在元素进行拖拽
 * position（文本流位置）：
 *      默认-将元素固定在页面上，脱离文本流
 *      click-点击后再固定，点击后脱离文本流
 *      never-始终不影响页面布局
 * overflow（是否允许超出页面范围）:
 *      默认-允许超出页面
 *      disabled-禁止超出页面
 *      auto-鼠标松开后回弹
 * 调用示例：v-mov="{title:true,position:'never',overflow:'auto'}"
 * 
 * 安装方式：main.js
 * import App from './App.vue'
 * import { installimgMov } from "@/directive/mov";
 * const app = createApp(App)
 * installimgMov(app);
 */

export const installimgMov = (app) => {
    app.directive('mov', (el, binding) => {
        // 获取到title的元素
        let title = el;
        if (!binding.value) {
            binding.value = { title: false, position: false, overflow: false }
        }
        if (binding.value.title) {
            title = el.querySelector('.title');
            if (title === null) {
                console.error('拖拽功能失效,类名为title的元素未找到,请检查或设置title参数为false')
                return;
            }
        }
        // 标题文本禁止框选
        title.style['user-select'] = 'none';
        // 设置鼠标样式
        title.style['cursor'] = 'move';
        // 设置元素定位
        const setElPosition = () => {
            el.style.position = 'fixed';
            el.style.zIndex = 999;
        }
        if (!binding.value.position) { setElPosition() }
        if (binding.value.position == 'never') {
            // 添加一个兄弟元素站位，以免影响元素布局
            let parent = el.parentNode
            let brother = document.createElement('div');
            let element = el.getBoundingClientRect()
            brother.style.width = element.width + 'px'
            brother.style.height = element.height + 'px'
            parent.insertBefore(brother, el.nextElementSibling)
            setElPosition()
        }
        // 元素回弹到页面边缘
        const backpage = () => {
            if (el.offsetLeft < 0) { el.style.left = 0 + 'px' }
            if (el.offsetTop < 0) { el.style.top = 0 + 'px' }
            if (el.offsetLeft + el.offsetWidth > document.documentElement.clientWidth) {
                el.style.left = document.documentElement.clientWidth - el.offsetWidth + 'px'
            }
            if (el.offsetTop + el.offsetHeight > document.documentElement.clientHeight) {
                el.style.top = document.documentElement.clientHeight - el.offsetHeight + 'px'
            }
        }
        // 当元素被按下时
        title.addEventListener('mousedown', (event) => {
            if (binding.value.position == 'click') { setElPosition() }
            // 获取鼠标按下坐标
            let X = event.clientX - el.offsetLeft;
            let Y = event.clientY - el.offsetTop;
            // 当元素被按下且移动时
            const mousemove = (event) => {
                // 获取鼠标的坐标
                el.style.left = event.clientX - X + 'px'
                el.style.top = event.clientY - Y + 'px'
                // 限制元素不能超出页面范围
                if (binding.value.overflow == 'disabled') {
                    backpage()
                }
            }
            title.addEventListener('mousemove', mousemove)
            // 解绑移动事件
            const mouseup = () => {
                if (binding.value.overflow == 'auto') {
                    backpage()
                }
                title.removeEventListener('mousemove', mousemove)
            }
            // 当元素被松开时
            title.addEventListener('mouseup', mouseup)
            // 当鼠标超出元素范围
            title.addEventListener('mouseleave', mouseup)
        })
    })
};
